<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\BaseController;
use App\Jobs\ArticleWeight;
use App\Jobs\CommentSubscribe;
use App\Models\Article;
use App\Models\Comment;
use App\Models\Star;
use App\Models\Subscribe;
use App\Services\BalanceService;
use App\Services\NotifyService;
use App\Services\SafeCheckService;
use Illuminate\Http\Request;

class CommentController extends BaseController
{
    public $model = Comment::class;

    public function index(Request $request) {
        $this->validate($request, [
            'entity_id' => 'required',
        ]);
        $entity_id = $request->input('entity_id');
        $entity = Article::find($entity_id);
        if (!$entity)
            return $this->failed('不存在');

        $parent_id = $request->input('parent_id', 0);
        $type = $request->input('type', 1);
        $child_per_page = $request->input('child_per_page', 5);
        $user_id = $this->getUserId();
        $list = Comment::cacheFor(3600)->cacheTags(['article:' . $entity_id. '_' . $entity->latest_comment_at])->withCertain('user', ['nickname', 'avatar_url'])
             ->withCount(['is_star' => function ($qr) use ($user_id) {
                 $qr->where('user_id', $user_id)->where('type', Star::TYPE_COMMENT);
             }])
            ->withCertain('reply.user', ['nickname', 'avatar_url'])
            ->withCertain('user', ['nickname', 'avatar_url'])
            ->type($type)->where('entity_id', $entity_id)
            ->parentId($parent_id)->orderBy("star_num", "desc")->orderBy("id", "desc");


        if ($parent_id != 0) {
            $list = $list->with(['child.user' => function($q) {
                $q->select('id', 'nickname', 'avatar_url');
            }, 'child.reply.user'=> function($q) {
                $q->select('id', 'nickname', 'avatar_url');
            }])
            ->with(['child.reply' => function($q) use($user_id) {
                $q->withCount(['is_star' => function ($qr) use ($user_id) {
                    $qr->where('user_id', $user_id)->where('type', Star::TYPE_COMMENT);
                }])->orderBy("star_num", "desc")->orderBy("id", "desc");
            }])
            ->with(['child' => function($q) use($user_id) {
                $q->withCount(['is_star' => function ($qr) use ($user_id) {
                    $qr->where('user_id', $user_id)->where('type', Star::TYPE_COMMENT);
                }])->orderBy("star_num", "desc")->orderBy("id", "desc");
            }]);
        }

        if ($parent_id == 0) {
            $per_page = per_page();
        } else {
            $per_page = $child_per_page;
        }
        $list = $list->paginate($per_page);

        if ($parent_id == 0) {
            foreach ($list as $item) {
                $child = Comment::cacheFor(3600)->cacheTags(['article:' . $entity_id. '_' . $entity->latest_comment_at])->with(['user' => function($q) {
                    $q->select('id', 'nickname', 'avatar_url');
                }, 'reply.user'=> function($q) {
                    $q->select('id', 'nickname', 'avatar_url');
                }])->with(['reply' => function($q) use($user_id) {
                    $q->withCount(['is_star' => function ($qr) use ($user_id) {
                        $qr->where('user_id', $user_id)->where('type', Star::TYPE_COMMENT);
                    }]);
                }])->withCount(['is_star' => function ($qr) use ($user_id) {
                    $qr->where('user_id', $user_id)->where('type', Star::TYPE_COMMENT);
                }])->where('parent_id', $item->id)->paginate($child_per_page);

                $arr = [
                    'list' => $child->items(),
                    'total' => $child->total(),
                    'has_more_page' => $child->hasMorePages(),
                ];
                $item->child = $arr;
            }
        }

        $info = [
            'comment_num' => $entity->comment_num
        ];
        return $this->paginate($list, $info);
    }

    public function test() {
        $user_id = $this->getUserId();
        $id = \request('id', 367);
        $list = Comment::withCertain('user', ['nickname', 'avatar_url'])
            ->withCount(['is_star' => function ($qr) use ($user_id) {
                $qr->where('user_id', $user_id)->where('type', Star::TYPE_COMMENT);
            }])
            ->withCertain('reply.user', ['nickname', 'avatar_url'])
            ->withCertain('user', ['nickname', 'avatar_url'])
            ->type(1)->where('id', $id)
            ->first();
        $list->child = ['list' => [], 'total' => 0];
        return $this->success($list);
    }


    /**
     * 评论
     * @param Request $request
     * @return mixed
     * @throws \Illuminate\Validation\ValidationException
     * @throws \Throwable
     */
    public function store(Request $request) {
        $this->validate($request, [
            'entity_id' => 'required',
            'message' => 'required',
        ]);
        $user = $this->getUser();
        $input = $request->input();

        try {
            return \DB::transaction(function () use($input, $user){
                $entity_model = new Article();
                $entity_result = $entity_model->find($input['entity_id']);
                if (!$entity_result)
                    throw new \Exception("ID对应数据不存在");

                $hit = SafeCheckService::handle(['type' => 'text', 'content' => $input['message']]);
                if ($hit)
                    return $this->failed('发布内容包含敏感词');

                $entity_result->comment_num += 1;
                $entity_result->latest_comment_at = time();
                $input['comment_string_length'] = mb_strlen($input['message']);

                $entity_result->save();

                if ($parent_id = ($input['comment_id'] ?? 0)) {
                    $comment = Comment::find($parent_id);
                    if (!$comment)
                        throw new \Exception("留言id不存在");
                    $comment->increment('reply_count', 1);
                    if ($comment->parent_id != 0) {
                        $input['reply_to_id'] = $comment->id;
                        $input['parent_id'] = $comment->parent_id;
                    } else {
                        $input['parent_id'] = $parent_id;
                    }
                }
                $input['user_id'] = $user->id;
                $input['entity_user_id'] = $entity_result->user_id;
                $info = $this->model::create($input);
                $id = $info->id;

                if ($parent_id) {
                    NotifyService::store($input['user_id'], 4, $input['entity_id'], $comment->user_id, $input['message'], $parent_id);
                } else {
                        $exists = Subscribe::where('user_id', $input['entity_user_id'])->where('template_id', Subscribe::TEMPLATE_COMMENT)->exists();
                        if ($exists && $input['user_id'] != $input['entity_user_id'])
                            $this->dispatch(new CommentSubscribe($id));

                    NotifyService::store($input['user_id'], 3, $input['entity_id'], $entity_result->user_id, $input['message'], $id);
                }
                $this->dispatch(new ArticleWeight($input['entity_id']));

                $exists = BalanceService::comment($user->id);
                $is_first = !$exists ? 1 : 0;

                $comment_info = Comment::withCertain('user', ['nickname', 'avatar_url'])
                    ->withCount(['is_star' => function ($qr) use ($user) {
                        $qr->where('user_id', $user->id)->where('type', Star::TYPE_COMMENT);
                    }])
                    ->withCertain('reply.user', ['nickname', 'avatar_url'])
                    ->withCertain('user', ['nickname', 'avatar_url'])
                    ->type(1)->where('id', $id)
                    ->first();
                if (!$parent_id)
                    $comment_info->child = ['list' => [], 'total' => 0];


                return $this->success([
                    'id' => $id,
                    'is_first' => $is_first,
                    'comment_info' => $comment_info
                ]);
            });
        } catch (\Exception $e) {
            \Log::error($e->getLine());
            return $this->failed($e->getMessage());
        }
    }

    /**
     * 删除
     * @param Request $request
     * @return mixed
     * @throws \Illuminate\Validation\ValidationException
     * @throws \Throwable
     */
    public function destroy(Request $request)
    {
        $this->validate($request, [
            'comment_id' => 'required',
        ]);
        $id = \request('comment_id');
        $comment = Comment::find($id);
        $entity_id = $comment->entity_id;
        if (!$comment)
            return $this->failed("评论不存在");
        if ($comment->user_id != $this->getUserId())
            return $this->failed("无权删除");

        $parent_id = $comment->parent_id;
        return \DB::transaction(function () use ($parent_id, $comment, $entity_id) {
            if ($parent_id == 0) {
                Comment::where('parent_id', $comment->id)->delete();
            }
//            $entity_model = new Article();
//            $entity_model->where('id', $comment->entity_id)->increment('comment_num', - ($comment->reply_count+1));
            $comment->delete();
            $comment_num = Comment::where('entity_id', $entity_id)->count();
            Article::where('id', $entity_id)->update(['comment_num' => $comment_num, 'latest_comment_at' => time()]);
            return $this->success($comment->id);
        });
    }


}

